<template>
  <div class="dashboard-wrapper">
    <div ref="dashboardRef" class="dashboard-container" :class="{ 'data-loaded': dataLoaded }">
    <!-- 加载遮罩层 -->
    <div v-if="loading" class="loading-overlay">
      <div class="loading-content">
        <div class="loading-animation">
          <div class="loading-spinner">
            <div class="spinner-ring"></div>
            <div class="spinner-ring"></div>
            <div class="spinner-ring"></div>
          </div>
          <div class="loading-particles">
            <div class="particle" v-for="i in 8" :key="i" :style="{ '--delay': i * 0.1 + 's' }"></div>
          </div>
        </div>
        <div class="loading-text">
          <h3>医美平台运营大屏</h3>
          <p>正在加载数据中...</p>
          <div class="loading-progress">
            <div class="progress-bar">
              <div class="progress-fill" :style="{ width: loadingProgress + '%' }"></div>
            </div>
            <span class="progress-text">{{ loadingProgress }}%</span>
          </div>
        </div>
        <div class="loading-tips">
          <div class="tip-item">
            <el-icon><DataLine /></el-icon>
            <span>正在获取核心指标数据</span>
          </div>
          <div class="tip-item">
            <el-icon><TrendCharts /></el-icon>
            <span>正在加载图表数据</span>
          </div>
          <div class="tip-item">
            <el-icon><Location /></el-icon>
            <span>正在初始化地图组件</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 头部标题 -->
    <div class="dashboard-header">
      <!-- 顶部通知栏 -->
      
      
      <!-- 主要内容区域 -->
      <div class="header-main">
        <!-- 左侧状态信息 -->
        <div class="header-left">
          <div class="status-icon">
            <el-icon><Message /></el-icon>
          </div>
          <span class="status-text">数据驱动医美未来!</span>
          <!-- 左侧装饰几何 -->
          <div class="left-decoration">
            <div class="angular-line line-1"></div>
            <div class="angular-line line-2"></div>
            <div class="geometric-shape shape-1"></div>
            <div class="geometric-shape shape-2"></div>
          </div>
        </div>
        
        <!-- 中央标题面板 -->
        <div class="header-center">
          <div class="title-panel">
            <div class="title-background">
              <div class="title-glow"></div>
              <div class="title-pattern"></div>
            </div>
            <h1 class="dashboard-title">医美平台运营大屏</h1>
            <div class="title-subtitle">Medical Aesthetics Platform Operations Dashboard</div>
            <!-- 几何装饰线条 -->
            <div class="geometric-decoration">
              <!-- 左侧3条平行斜线 -->
              <div class="left-diagonal-lines">
                <div class="diagonal-line line-1"></div>
                <div class="diagonal-line line-2"></div>
                <div class="diagonal-line line-3"></div>
              </div>
              <!-- 右侧3条平行斜线 -->
              <div class="right-diagonal-lines">
                <div class="diagonal-line line-1"></div>
                <div class="diagonal-line line-2"></div>
                <div class="diagonal-line line-3"></div>
              </div>
              <!-- 底部水平连接线 -->
              <div class="bottom-connector-line"></div>
            </div>
          </div>
        </div>
        
        <!-- 右侧时间和操作 -->
        <div class="header-right">
          <div class="time-info">
            <div class="current-time">{{ currentTime }}</div>
            <div class="time-separator">|</div>
            <div class="current-date">{{ currentDate }}</div>
            <div class="time-separator">|</div>
            <div class="current-day">{{ currentDay }}</div>
          </div>
        
          <!-- 右侧装饰几何 -->
          <div class="right-decoration">
            <div class="angular-line line-3"></div>
            <div class="angular-line line-4"></div>
            <div class="geometric-shape shape-3"></div>
          </div>
        </div>
      </div>
      
      <!-- 底部装饰区域 -->
      <div class="header-decoration">
        <div class="decoration-line"></div>
        <div class="decoration-nodes">
          <div class="node"></div>
          <div class="node"></div>
          <div class="node"></div>
        </div>
        <div class="decoration-pattern">
          <div class="pattern-line"></div>
          <div class="pattern-line"></div>
          <div class="pattern-line"></div>
            </div>
            </div>
          </div>

    <!-- 核心指标 -->
    <div class="metrics-grid">
      <DataCard
        v-for="metric in displayCoreMetrics"
        :key="metric.title"
        :title="metric.title"
        :value="metric.value"
        :icon="metric.icon"
        :icon-color="metric.color"
        :loading="loading"
        :formatter="metric.formatter"
      />
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧面板 -->
      <div class="left-panel">
        <!-- 商品销量TOP10 -->
        <div class="ranking-card">
          <div class="card-header">
            <h3>商品销量TOP10排行榜</h3>
            </div>
            <div class="card-content">
            <div v-if="displayProducts.length === 0" class="empty-content">
              <div v-if="selectedCity" class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">{{ selectedCity }}暂无商品数据</p>
              </div>
              <div v-else-if="socketConnected" class="loading-state">
                <div class="loading-spinner-small"></div>
                <p>数据加载中...</p>
              </div>
              <div v-else class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">Socket.IO未连接</p>
              </div>
            </div>
            <div 
              v-else 
              ref="rankingListRef"
              class="ranking-list"
              @mouseenter="pauseAutoScroll"
              @mouseleave="resumeAutoScroll"
            >
              <div 
                v-for="(item, index) in displayProducts" 
                :key="item._id || index"
                class="ranking-item"
              >
                <div class="rank-number">{{ index + 1 }}</div>
                <div class="item-info">
                  <div class="item-name">{{ item.title || item.name }}</div>
                  <div class="item-details">
                    <span class="price">¥{{ item.price }}</span>
                    <span class="hospital">{{ item.hospital }}</span>
                </div>
                <div class="view-count">{{ item.viewCount }}次</div>
              </div>
            </div>
          </div>
              </div>
            </div>


        <!-- 价格区间分析 -->
        <div class="chart-card">
          <div class="card-header">
            <h3>价格区间分析</h3>
          </div>
          <div class="card-content">
            <div v-if="priceAnalysisData.length === 0" class="empty-content">
              <div v-if="selectedCity" class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">{{ selectedCity }}暂无价格分析数据</p>
              </div>
              <div v-else-if="socketConnected" class="loading-state">
                <div class="loading-spinner-small"></div>
                <p>价格分析数据加载中...</p>
              </div>
              <div v-else class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">Socket.IO未连接</p>
              </div>
            </div>
            <div v-else ref="priceChartRef" class="chart-container"></div>
          </div>
        </div>
    </div>

      <!-- 中间地图区 -->
      <div class="center-panel">
        <div class="map-card">
          <div class="card-header">
            <h3>全国医院分布地图</h3>
            <!-- 省份选择状态指示器 -->
            <div v-if="selectedCity" class="province-status">
              <span class="status-label">当前查看：</span>
              <span class="province-name">{{ selectedCity }}</span>
              <el-button 
                type="primary" 
                size="small" 
                @click="resetToNationalData"
                class="reset-btn"
              >
                返回全国
              </el-button>
            </div>
            <!-- Socket.IO连接状态 -->
            <div class="connection-status">
              <span 
                :class="['status-dot', socketConnected ? 'connected' : 'disconnected']"
                :title="socketConnected ? 'Socket.IO已连接' : 'Socket.IO未连接'"
              ></span>
              <span class="status-text">
                {{ socketConnected ? '实时连接' : '离线模式' }}
              </span>
            </div>
          </div>
          <div class="card-content">
            <div class="map-container">
              <ChinaMap 
                :key="`map-${mapUpdateCounter}`"
                :data="hospitalDistribution" 
                @province-click="handleProvinceClick"
                @province-hover="handleProvinceHover"
                @province-leave="handleProvinceLeave"
                @map-blank-click="handleMapBlankClick"
              />
            </div>
          </div>
        </div>
    </div>

      <!-- 右侧面板 -->
      <div class="right-panel">

        <!-- 医生专业分布 -->
        <div class="chart-card">
          <div class="card-header">
            <h3>医生专业分布</h3>
          </div>
          <div class="card-content">
            <div v-if="displayDoctorSpecialtyData.length === 0" class="empty-content">
              <div v-if="selectedCity" class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">{{ selectedCity }}暂无医生数据</p>
              </div>
              <div v-else-if="socketConnected" class="loading-state">
                <div class="loading-spinner-small"></div>
                <p>医生专业分布数据加载中...</p>
              </div>
              <div v-else class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">Socket.IO未连接</p>
              </div>
            </div>
            <div v-else ref="doctorChartRef" class="chart-container"></div>
          </div>
        </div>

        <!-- 热门项目预约趋势 -->
        <div class="chart-card">
          <div class="card-header">
            <h3>热门项目预约趋势</h3>
          </div>
          <div class="card-content">
            <div v-if="trendDataForChart.length === 0" class="empty-content">
              <div v-if="selectedCity" class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">{{ selectedCity }}暂无趋势数据</p>
              </div>
              <div v-else-if="socketConnected" class="loading-state">
                <div class="loading-spinner-small"></div>
                <p>趋势数据加载中...</p>
              </div>
              <div v-else class="no-data-state">
                <p>暂无数据</p>
                <p style="font-size: 12px; color: #999; margin-top: 8px;">Socket.IO未连接</p>
              </div>
            </div>
            <div v-else ref="trendChartRef" class="chart-container"></div>
          </div>
        </div>
      </div>
    </div>

    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, computed, nextTick, watch } from 'vue'
import { ElButton, ElIcon, ElMessage } from 'element-plus'
import { TrendCharts, DataLine, Location, Message } from '@element-plus/icons-vue'
import { io } from 'socket.io-client'
import * as echarts from 'echarts'
// @ts-ignore
import DataCard from '@/components/DataCard.vue'
// @ts-ignore
import ChinaMap from '@/components/ChinaMap.vue'

// 接口定义
interface CoreMetric {
  title: string
  value: number
  icon: string
  color: string
  formatter?: (value: number | string) => string
}

interface ProductTop10Item {
  _id: string
  title?: string
  name?: string
  price: number
  hospital: string
  viewCount: number
}

interface DoctorSpecialtyItem {
  specialty: string
  count: number
  percentage: string
}

interface HospitalDistributionItem {
  name: string
  city: string
  value: number
  hospitals: Array<{
    name: string
    rating: number
    address?: string
    category?: string
    isHot?: boolean
  }>
  avgRating: number
}

interface HospitalStats {
  totalCities: number
  maxHospitals: number
  avgRating: number
}

// 响应式数据
const loading = ref(true)
const dataLoaded = ref(false)
const loadingProgress = ref(0)
const loadingSteps = ref([
  { name: '初始化系统', progress: 10 },
  { name: '连接数据源', progress: 25 },
  { name: '获取核心指标', progress: 40 },
  { name: '加载图表数据', progress: 60 },
  { name: '初始化地图', progress: 80 },
  { name: '完成加载', progress: 100 }
])

// 时间相关数据
const currentTime = ref('')
const currentDate = ref('')
const currentDay = ref('')

// 城市联动相关
const selectedCity = ref<string | null>(null)
const cityFilteredData = ref({
  products: [] as ProductTop10Item[],
  doctors: [] as DoctorSpecialtyItem[],
  hospitals: [] as HospitalDistributionItem[],
  priceAnalysis: [] as any[],
  coreMetrics: {
    totalProducts: 0,
    totalHospitals: 0,
    totalDoctors: 0
  }
})

// 图表引用
const priceChartRef = ref<HTMLElement>()
const doctorChartRef = ref<HTMLElement>()
const trendChartRef = ref<HTMLElement>()
const rankingListRef = ref<HTMLElement>()
let priceChart: echarts.ECharts | null = null
let doctorChart: echarts.ECharts | null = null
let trendChart: echarts.ECharts | null = null

// 排行榜自动滚动相关
const autoScrollEnabled = ref(true)
const scrollInterval = ref<number | null>(null)
const scrollSpeed = ref(50) // 滚动速度，毫秒
const scrollStep = ref(1) // 每次滚动的像素数
const isScrollingToTop = ref(false) // 是否正在滚动到顶部

// 自适应缩放相关
const dashboardRef = ref<HTMLElement>()
const scale = ref(1)
const baseWidth = 1920 // 设计稿基准宽度
const baseHeight = 1080 // 设计稿基准高度

// Socket.IO 相关
const socket = ref<any>(null)
const socketConnected = ref(false)

// 数据缓存 - 存储所有原始数据
const allDataCache = ref({
  coreMetrics: {
    totalProducts: 0,
    totalHospitals: 0,
    totalDoctors: 0
  },
  productTop10: [] as ProductTop10Item[],
  doctorSpecialties: [] as DoctorSpecialtyItem[],
  hospitalDistribution: [] as HospitalDistributionItem[],
  priceAnalysis: [] as any[],
  timestamp: new Date()
})

const coreMetrics = ref<CoreMetric[]>([
  { 
    title: '产品总数', 
    value: 42, 
    icon: 'Box', 
    color: '#66bb6a'
  },
  { 
    title: '医院总数', 
    value: 32, 
    icon: 'OfficeBuilding', 
    color: '#ffa726'
  },
  { 
    title: '医生总数', 
    value: 55, 
    icon: 'User', 
    color: '#ef5350'
  }
])

const productTop10 = ref<ProductTop10Item[]>([])
const doctorSpecialties = ref<DoctorSpecialtyItem[]>([])
const hospitalDistribution = ref<HospitalDistributionItem[]>([])
const mapUpdateCounter = ref(0) // 用于强制地图重新渲染
const hospitalStats = reactive<HospitalStats>({
  totalCities: 0,
  maxHospitals: 0,
  avgRating: 0
})


// 计算属性 - 价格分析数据（支持城市过滤）
const priceAnalysisData = computed(() => {
  console.log('priceAnalysisData 计算:', {
    selectedCity: selectedCity.value,
    cityProducts: cityFilteredData.value.products,
    cityProductsLength: cityFilteredData.value.products.length,
    globalPriceAnalysis: allDataCache.value.priceAnalysis
  })
  
  if (selectedCity.value) {
    // 如果选中了城市但没有产品数据，直接返回空数组显示"暂无数据"
    if (cityFilteredData.value.products.length === 0) {
      console.log(`${selectedCity.value}没有产品数据，价格分析显示暂无数据`)
      return []
    }
    
    // 优先使用城市过滤数据中的价格分析
    if (cityFilteredData.value.priceAnalysis && cityFilteredData.value.priceAnalysis.length > 0) {
      console.log(`${selectedCity.value}使用缓存的价格分析数据:`, cityFilteredData.value.priceAnalysis)
      return cityFilteredData.value.priceAnalysis
    }
    
    // 基于城市产品数据计算价格分析
      const cityProducts = cityFilteredData.value.products
      const priceRanges = [
        { name: '500-1000', min: 500, max: 1000, color: '#00ffff' },
        { name: '1000-2000', min: 1000, max: 2000, color: '#ff00ff' },
        { name: '2000-3000', min: 2000, max: 3000, color: '#ffff00' },
        { name: '3000-5000', min: 3000, max: 5000, color: '#00ff00' },
        { name: '5000+', min: 5000, max: Infinity, color: '#ff6600' }
      ]
      
      const cityPriceAnalysis = priceRanges.map(range => {
        const matchingProducts = cityProducts.filter(product => 
          product.price >= range.min && product.price < range.max
        )
        console.log(`价格区间 ${range.name} (${range.min}-${range.max}):`, {
          匹配产品数量: matchingProducts.length,
          匹配的产品: matchingProducts.map(p => ({ name: p.title, price: p.price }))
        })
        return {
          name: range.name,
          value: matchingProducts.length,
          color: range.color
        }
      })
      
      console.log(`${selectedCity.value}的价格分析:`, cityPriceAnalysis)
      console.log(`${selectedCity.value}的所有产品价格:`, cityProducts.map(p => ({ name: p.title, price: p.price })))
      return cityPriceAnalysis
  }
  
  // 返回全局价格分析数据
  console.log('全局价格分析数据:', allDataCache.value.priceAnalysis)
  if (allDataCache.value.priceAnalysis && allDataCache.value.priceAnalysis.length > 0) {
    return allDataCache.value.priceAnalysis
  }
  
  // 如果没有缓存数据，等待Socket.IO数据加载
  console.log('价格分析数据为空，等待Socket.IO数据加载...')
  return []
})

// 计算属性 - 医生专业分布数据
const doctorSpecialtyData = computed(() => 
  doctorSpecialties.value.map(item => ({
    name: item.specialty,
    value: item.count,
    color: getSpecialtyColor(item.specialty)
  }))
)

// 计算属性 - 显示的产品数据（支持城市过滤，只显示前10个）
const displayProducts = computed(() => {
  console.log('displayProducts 计算:', {
    selectedCity: selectedCity.value,
    cityProducts: cityFilteredData.value.products,
    cityProductsLength: cityFilteredData.value.products.length,
    globalProducts: productTop10.value
  })
  
  let products = []
  
  if (selectedCity.value) {
    // 如果选中了城市，使用城市数据（即使为空也要使用，这样会显示"暂无数据"）
    console.log('使用城市产品数据:', cityFilteredData.value.products)
    products = cityFilteredData.value.products
  } else {
    console.log('使用全局产品数据:', productTop10.value)
    products = productTop10.value
  }
  
  // 如果选中了城市但没有数据，返回空数组让组件显示"暂无数据"
  if (selectedCity.value && products.length === 0) {
    console.log(`${selectedCity.value}产品数据为空，显示暂无数据`)
    return []
  }
  
  // 如果没有选中城市且全局数据为空，等待Socket.IO数据
  if (!selectedCity.value && products.length === 0) {
    console.log('全局产品数据为空，等待Socket.IO数据加载...')
    return []
  }
  
  // 只返回前10个产品
  const top10Products = products.slice(0, 10)
  console.log(`显示前10个产品，共${top10Products.length}个:`, top10Products)
  
  return top10Products
})


// 计算属性 - 显示的医生专业分布数据（支持城市过滤）
const displayDoctorSpecialtyData = computed(() => {
  console.log('displayDoctorSpecialtyData 计算:', {
    selectedCity: selectedCity.value,
    cityDoctors: cityFilteredData.value.doctors,
    cityDoctorsLength: cityFilteredData.value.doctors.length,
    globalDoctors: doctorSpecialtyData.value
  })
  
  if (selectedCity.value) {
    // 如果选中了城市但没有医生数据，直接返回空数组显示"暂无数据"
    if (cityFilteredData.value.doctors.length === 0) {
      console.log(`${selectedCity.value}没有医生数据，医生专业分布显示暂无数据`)
      return []
    }
    
    // 使用城市医生数据
    console.log('使用城市医生数据:', cityFilteredData.value.doctors)
    const cityDoctorData = cityFilteredData.value.doctors.map(item => ({
      name: item.specialty,
      value: item.count,
      color: getSpecialtyColor(item.specialty)
    }))
    console.log(`${selectedCity.value}城市医生数据转换后:`, cityDoctorData)
    return cityDoctorData
  }
  
  console.log('使用全局医生数据:', doctorSpecialtyData.value)
  const globalDoctorData = doctorSpecialtyData.value
  console.log('全局医生数据转换后:', globalDoctorData)
  
  // 确保有数据，如果没有则等待Socket.IO数据
  if (globalDoctorData.length === 0) {
    console.log('医生专业分布数据为空，等待Socket.IO数据加载...')
    return []
  }
  
  return globalDoctorData
})

// 计算属性 - 显示的核心指标数据（支持城市过滤）
const displayCoreMetrics = computed(() => {
  console.log('displayCoreMetrics 计算:', {
    selectedCity: selectedCity.value,
    coreMetrics: cityFilteredData.value.coreMetrics,
    hasCoreMetrics: !!cityFilteredData.value.coreMetrics
  })
  
  if (selectedCity.value && cityFilteredData.value.coreMetrics) {
    console.log('使用城市数据:', cityFilteredData.value.coreMetrics)
    return [
      {
        title: '产品总数',
        value: cityFilteredData.value.coreMetrics.totalProducts,
        icon: 'Box',
        color: '#66bb6a'
      },
      {
        title: '医院总数',
        value: cityFilteredData.value.coreMetrics.totalHospitals,
        icon: 'OfficeBuilding',
        color: '#ffa726'
      },
      {
        title: '医生总数',
        value: cityFilteredData.value.coreMetrics.totalDoctors,
        icon: 'User',
        color: '#ef5350'
      }
    ]
  }
  console.log('使用全局数据:', coreMetrics.value)
  // 返回全局数据
  return coreMetrics.value
})

// 计算属性 - 趋势数据（支持城市过滤）
const trendData = computed(() => {
  console.log('trendData 计算:', {
    selectedCity: selectedCity.value,
    cityProducts: cityFilteredData.value.products
  })
  
  if (selectedCity.value) {
    // 如果选中了城市但没有产品数据，返回空数组显示"暂无数据"
    if (cityFilteredData.value.products.length === 0) {
      console.log(`${selectedCity.value}产品数据为空，趋势数据也显示暂无数据`)
      return []
    }
    
    // 基于城市产品数据生成趋势数据
    const cityProducts = cityFilteredData.value.products
    const baseVolume = Math.min(cityProducts.length * 20, 100) // 基于产品数量调整基数
    
    // 生成城市相关的趋势数据（模拟数据，但基于城市产品数量）
    const cityTrendData = [
      {
        name: '预约量',
        data: [
          Math.round(baseVolume * 0.8),
          Math.round(baseVolume * 0.9),
          Math.round(baseVolume * 0.7),
          Math.round(baseVolume * 1.0),
          Math.round(baseVolume * 0.85),
          Math.round(baseVolume * 1.1)
        ],
        color: '#4fc3f7',
        type: 'line' as const
      },
      {
        name: '完成量',
        data: [
          Math.round(baseVolume * 0.75),
          Math.round(baseVolume * 0.85),
          Math.round(baseVolume * 0.65),
          Math.round(baseVolume * 0.9),
          Math.round(baseVolume * 0.8),
          Math.round(baseVolume * 1.0)
        ],
        color: '#66bb6a',
        type: 'line' as const
      }
    ]
    
    console.log(`${selectedCity.value}的趋势数据:`, cityTrendData)
    return cityTrendData
  }
  
  // 返回全局趋势数据
  return [
    {
      name: '预约量',
      data: [85, 92, 78, 95, 88, 102],
      color: '#4fc3f7',
      type: 'line' as const
    },
    {
      name: '完成量',
      data: [78, 85, 72, 88, 82, 95],
      color: '#66bb6a',
      type: 'line' as const
    }
  ]
})

// const trendCategories = ['4月', '5月', '6月', '7月', '8月', '9月']

// 计算属性 - 趋势数据转换为LineChart格式
const trendDataForChart = computed(() => {
  const trend = trendData.value
  console.log('trendDataForChart 计算:', { trend })
  
  if (!trend || trend.length === 0) {
    console.log('趋势数据为空，返回空数组')
    return []
  }
  
  // 将趋势数据转换为折线图期望的格式，保留完整的月份数据
  const result = trend.map(item => ({
    name: item.name,
    data: item.data || [0, 0, 0, 0, 0], // 保留完整的月份数据数组
    color: item.color
  }))
  
  console.log('转换后的趋势数据:', result)
  return result
})


// 获取专业对应的固定颜色
const getSpecialtyColor = (specialty: string) => {
  const colorMap: { [key: string]: string } = {
    '眼部整形': '#ff4757',        // 红色
    '皮肤美容': '#4fc3f7',        // 蓝色
    '微整形': '#ab47bc',          // 紫色
    '脂肪填充': '#66bb6a',        // 绿色
    '面部轮廓': '#ffa726',        // 橙色
    '鼻部整形': '#ef5350',        // 深红色
    '胸部整形': '#26c6da',        // 青色
    '身体塑形': '#ff6b35',        // 橙红色
    '抗衰老': '#9c27b0',          // 深紫色
    '激光美容': '#00bcd4',        // 浅青色
    '隆鼻手术': '#e91e63',        // 粉红色
    '肉毒素注射': '#3f51b5',      // 靛蓝色
    '其他注射': '#795548',        // 棕色
    '其他': '#607d8b',            // 蓝灰色
    '激光治疗': '#ff9800',        // 深橙色
    '水光针': '#8bc34a',          // 浅绿色
    '美白针': '#9c27b0',          // 紫色
    '除皱': '#f44336',            // 红色
    '玻尿酸': '#2196f3',          // 蓝色
    '瘦脸针': '#ff5722'           // 深橙色
  }
  return colorMap[specialty] || '#607d8b' // 默认使用蓝灰色
}


// Socket.IO 连接管理
const initSocketIO = () => {
  try {
    console.log('🚀 初始化Socket.IO连接...')
    
    // 创建Socket.IO连接
    socket.value = io('http://localhost:3000', {
      query: {
        userId: 'dashboard-user-' + Date.now()
      },
      transports: ['websocket', 'polling']
    })
    
    // 连接成功
    socket.value.on('connect', () => {
      console.log('✅ Socket.IO连接成功:', socket.value.id)
      socketConnected.value = true
      
      // 加入仪表板更新房间
      socket.value.emit('join-dashboard-updates', {
        userId: 'dashboard-user-' + Date.now()
      })
      
      // 请求所有数据
      requestAllData()
    })
    
    // 连接断开
    socket.value.on('disconnect', (reason: string) => {
      console.log('❌ Socket.IO连接断开:', reason)
      socketConnected.value = false
    })
    
    // 连接错误
    socket.value.on('connect_error', (error: any) => {
      console.error('❌ Socket.IO连接错误:', error)
      socketConnected.value = false
    })
    
    // 监听所有数据响应
    socket.value.on('all-data-response', (data: any) => {
      console.log('📥 收到所有数据响应:', data)
      if (data.success) {
        handleAllDataResponse(data.data)
      } else {
        console.error('获取所有数据失败:', data.message)
        ElMessage.error('获取数据失败: ' + data.message)
      }
    })
    
    // 监听省份数据响应
    socket.value.on('province-data-response', (data: any) => {
      console.log('📥 收到省份数据响应:', data)
      if (data.success) {
        handleProvinceDataResponse(data.data)
      } else {
        console.error('获取省份数据失败:', data.message)
        ElMessage.error('获取省份数据失败: ' + data.message)
      }
    })
    
    // 监听实时数据更新
    socket.value.on('dashboard:update', (data: any) => {
      console.log('🔄 收到实时数据更新:', data)
      handleRealtimeUpdate(data)
    })
    
  } catch (error) {
    console.error('❌ Socket.IO初始化失败:', error)
  }
}

// 请求所有数据
const requestAllData = () => {
  if (socket.value && socketConnected.value) {
    console.log('📡 请求所有数据...')
    socket.value.emit('request-all-data', {
      userId: 'dashboard-user-' + Date.now()
    })
  } else {
    console.warn('⚠️ Socket.IO未连接，无法请求数据')
  }
}

// 请求省份数据
const requestProvinceData = (province: string) => {
  if (socket.value && socketConnected.value) {
    console.log(`📡 请求${province}省份数据...`)
    socket.value.emit('request-province-data', {
      province: province,
      userId: 'dashboard-user-' + Date.now()
    })
  } else {
    console.warn('⚠️ Socket.IO未连接，无法请求省份数据')
  }
}

// 处理所有数据响应
const handleAllDataResponse = (data: any) => {
  console.log('🔄 处理所有数据响应:', data)
  
  try {
    // 更新缓存
    allDataCache.value = {
      coreMetrics: data.statistics || {
        totalProducts: data.statistics?.totalProducts || 0,
        totalHospitals: data.statistics?.totalHospitals || 0,
        totalDoctors: data.statistics?.totalDoctors || 0
      },
      productTop10: data.products || [],
      doctorSpecialties: data.doctors ? generateDoctorSpecialtiesFromDoctors(data.doctors) : [],
      hospitalDistribution: data.hospitals ? generateHospitalDistributionFromHospitals(data.hospitals) : [],
      priceAnalysis: data.priceAnalysis || generatePriceAnalysisFromProducts(data.products || []),
      timestamp: new Date()
    }
    
    console.log('🔄 生成的价格分析数据:', allDataCache.value.priceAnalysis)
    console.log('🔄 生成的医生专业分布数据:', allDataCache.value.doctorSpecialties)
    
    // 应用到组件
    applyDataToComponents(allDataCache.value)
    
    console.log('✅ 所有数据更新完成')
    
  } catch (error) {
    console.error('❌ 处理所有数据响应失败:', error)
  }
}

// 处理省份数据响应
const handleProvinceDataResponse = async (data: any) => {
  console.log('🔄 处理省份数据响应:', data)
  
  try {
    // 设置选中的城市
    selectedCity.value = data.province
    
    if (data.hasData) {
      // 更新城市过滤数据
      cityFilteredData.value = {
        products: data.products || [],
        doctors: data.doctorSpecialtyDistribution || [],
        hospitals: data.hospitals || [],
        priceAnalysis: data.priceAnalysis || [],
        coreMetrics: data.statistics || {
          totalProducts: 0,
          totalHospitals: 0,
          totalDoctors: 0
        }
      }
      
      console.log(`✅ ${data.province}省份数据更新完成:`, cityFilteredData.value)
      console.log('当前selectedCity:', selectedCity.value)
      console.log('当前cityFilteredData:', cityFilteredData.value)
      
    } else {
      console.log(`ℹ️ ${data.province}暂无数据，显示空状态`)
      // 设置空数据，让所有组件显示"暂无数据"
      cityFilteredData.value = {
        products: [],
        doctors: [],
        hospitals: [],
        priceAnalysis: [],
        coreMetrics: {
          totalProducts: 0,
          totalHospitals: 0,
          totalDoctors: 0
        }
      }
    }
    
    // 使用nextTick确保DOM立即更新
    await nextTick()
    
    // 立即触发计算属性重新计算
    console.log('📊 计算属性重新计算完成')
    console.log('displayProducts:', displayProducts.value)
    console.log('displayDoctorSpecialtyData:', displayDoctorSpecialtyData.value)
    console.log('displayCoreMetrics:', displayCoreMetrics.value)
    console.log('priceAnalysisData:', priceAnalysisData.value)
    console.log('trendData:', trendData.value)
    
  } catch (error) {
    console.error('❌ 处理省份数据响应失败:', error)
  }
}

// 数据比对工具函数
const deepCompare = (obj1: any, obj2: any): boolean => {
  if (obj1 === obj2) return true
  if (obj1 == null || obj2 == null) return false
  if (typeof obj1 !== typeof obj2) return false
  
  if (Array.isArray(obj1) && Array.isArray(obj2)) {
    if (obj1.length !== obj2.length) return false
    return obj1.every((item, index) => deepCompare(item, obj2[index]))
  }
  
  if (typeof obj1 === 'object') {
    const keys1 = Object.keys(obj1)
    const keys2 = Object.keys(obj2)
    if (keys1.length !== keys2.length) return false
    return keys1.every(key => deepCompare(obj1[key], obj2[key]))
  }
  
  return obj1 === obj2
}

// 智能数据更新函数
const smartUpdateData = (updateType: string, newData: any, currentData: any) => {
  console.log(`🔍 比对${updateType}数据变化...`)
  
  // 深度比对数据是否真的发生了变化
  if (deepCompare(newData, currentData)) {
    console.log(`✅ ${updateType}数据无变化，跳过更新`)
    return false
  }
  
  console.log(`🔄 ${updateType}数据有变化，执行更新`)
  return true
}

// 特定数据类型的智能更新函数
const smartUpdateProductData = (newData: any, currentData: any) => {
  if (!Array.isArray(newData) || !Array.isArray(currentData)) {
    return !deepCompare(newData, currentData)
  }
  
  // 比对商品TOP10的关键字段：title, viewCount, price
  if (newData.length !== currentData.length) {
    console.log('📦 商品数量发生变化')
    return true
  }
  
  for (let i = 0; i < newData.length; i++) {
    const newItem = newData[i]
    const currentItem = currentData[i]
    
    if (newItem.title !== currentItem.title || 
        newItem.viewCount !== currentItem.viewCount || 
        newItem.price !== currentItem.price) {
      console.log(`📦 商品${i+1}数据发生变化:`, {
        title: { old: currentItem.title, new: newItem.title },
        viewCount: { old: currentItem.viewCount, new: newItem.viewCount },
        price: { old: currentItem.price, new: newItem.price }
      })
      return true
    }
  }
  
  return false
}

const smartUpdateDoctorData = (newData: any, currentData: any) => {
  if (!Array.isArray(newData) || !Array.isArray(currentData)) {
    return !deepCompare(newData, currentData)
  }
  
  // 比对医生专业分布的关键字段：specialty, count, percentage
  if (newData.length !== currentData.length) {
    console.log('👨‍⚕️ 医生专业数量发生变化')
    return true
  }
  
  for (let i = 0; i < newData.length; i++) {
    const newItem = newData[i]
    const currentItem = currentData[i]
    
    if (newItem.specialty !== currentItem.specialty || 
        newItem.count !== currentItem.count || 
        newItem.percentage !== currentItem.percentage) {
      console.log(`👨‍⚕️ 医生专业${i+1}数据发生变化:`, {
        specialty: { old: currentItem.specialty, new: newItem.specialty },
        count: { old: currentItem.count, new: newItem.count },
        percentage: { old: currentItem.percentage, new: newItem.percentage }
      })
      return true
    }
  }
  
  return false
}

const smartUpdateHospitalData = (newData: any, currentData: any) => {
  if (!Array.isArray(newData) || !Array.isArray(currentData)) {
    return !deepCompare(newData, currentData)
  }
  
  // 比对医院分布的关键字段：name, value, avgRating
  if (newData.length !== currentData.length) {
    console.log('🏥 医院数量发生变化')
    return true
  }
  
  for (let i = 0; i < newData.length; i++) {
    const newItem = newData[i]
    const currentItem = currentData[i]
    
    if (newItem.name !== currentItem.name || 
        newItem.value !== currentItem.value || 
        newItem.avgRating !== currentItem.avgRating) {
      console.log(`🏥 医院${i+1}数据发生变化:`, {
        name: { old: currentItem.name, new: newItem.name },
        value: { old: currentItem.value, new: newItem.value },
        avgRating: { old: currentItem.avgRating, new: newItem.avgRating }
      })
      return true
    }
  }
  
  return false
}

// 更新统计
const updateStats = ref({
  totalUpdates: 0,
  skippedUpdates: 0,
  lastUpdateTime: null as Date | null,
  updateHistory: [] as Array<{type: string, hasChanges: boolean, timestamp: Date}>
})

// 排行榜自动滚动方法
const startAutoScroll = () => {
  if (!autoScrollEnabled.value || !rankingListRef.value) return
  
  // 清除之前的定时器
  if (scrollInterval.value) {
    clearInterval(scrollInterval.value)
  }
  
  scrollInterval.value = setInterval(() => {
    if (!rankingListRef.value || !autoScrollEnabled.value) return
    
    const element = rankingListRef.value
    const maxScrollTop = element.scrollHeight - element.clientHeight
    
    // 如果内容高度小于容器高度，不需要滚动
    if (maxScrollTop <= 0) return
    
    // 如果正在滚动到顶部，跳过这次滚动
    if (isScrollingToTop.value) return
    
    // 如果已经滚动到底部，平滑重置到顶部
    if (element.scrollTop >= maxScrollTop - 2) {
      isScrollingToTop.value = true
      
      // 平滑滚动到顶部
      element.scrollTo({
        top: 0,
        behavior: 'smooth'
      })
      
      // 等待滚动完成后重置状态
      setTimeout(() => {
        isScrollingToTop.value = false
      }, 500) // 等待平滑滚动完成
    } else {
      // 继续向下滚动
      element.scrollTop += scrollStep.value
    }
  }, scrollSpeed.value)
}

const stopAutoScroll = () => {
  if (scrollInterval.value) {
    clearInterval(scrollInterval.value)
    scrollInterval.value = null
  }
}

const pauseAutoScroll = () => {
  autoScrollEnabled.value = false
  stopAutoScroll()
}

const resumeAutoScroll = () => {
  autoScrollEnabled.value = true
  startAutoScroll()
}

// 处理实时数据更新
const handleRealtimeUpdate = async (data: any) => {
  console.log('🔄 处理实时数据更新:', data)
  
  try {
    const { updateType, data: updateData } = data
    let hasChanges = false
    const startTime = Date.now()
    
    switch (updateType) {
      case 'product-top10':
        console.log('📦 检查商品TOP10数据变化...')
        if (smartUpdateProductData(updateData, productTop10.value)) {
          productTop10.value = updateData
          allDataCache.value.productTop10 = updateData
          hasChanges = true
          console.log('✅ 商品TOP10数据已更新')
        }
        break
        
      case 'price-analysis':
        console.log('💰 检查价格分析数据变化...')
        if (smartUpdateData('价格分析', updateData, allDataCache.value.priceAnalysis)) {
          allDataCache.value.priceAnalysis = updateData
          hasChanges = true
          console.log('✅ 价格分析数据已更新')
        }
        break
        
      case 'doctor-specialties':
        console.log('👨‍⚕️ 检查医生专业分布数据变化...')
        if (smartUpdateDoctorData(updateData, doctorSpecialties.value)) {
          doctorSpecialties.value = updateData
          allDataCache.value.doctorSpecialties = updateData
          hasChanges = true
          console.log('✅ 医生专业分布数据已更新')
        }
        break
        
      case 'hospital-distribution':
        console.log('🏥 检查医院分布数据变化...')
        console.log('🏥 新数据:', updateData)
        console.log('🏥 当前数据:', hospitalDistribution.value)
        
        if (smartUpdateHospitalData(updateData, hospitalDistribution.value)) {
          console.log('🏥 数据有变化，开始更新...')
          hospitalDistribution.value = updateData
          allDataCache.value.hospitalDistribution = updateData
          updateHospitalStats()
          hasChanges = true
          console.log('✅ 医院分布数据已更新:', hospitalDistribution.value)
          
          // 强制触发地图重新渲染
          mapUpdateCounter.value++
          console.log('🗺️ 地图更新计数器:', mapUpdateCounter.value)
          
          nextTick(() => {
            console.log('🗺️ 强制触发地图重新渲染')
          })
        } else {
          console.log('🏥 数据无变化，跳过更新')
        }
        break
        
      case 'core-metrics':
        console.log('📊 检查核心指标数据变化...')
        const currentMetrics = {
          totalProducts: coreMetrics.value[0].value,
          totalHospitals: coreMetrics.value[1].value,
          totalDoctors: coreMetrics.value[2].value
        }
        
        if (smartUpdateData('核心指标', updateData, currentMetrics)) {
          if (updateData.totalProducts !== undefined) {
            coreMetrics.value[0].value = updateData.totalProducts
            allDataCache.value.coreMetrics.totalProducts = updateData.totalProducts
          }
          if (updateData.totalHospitals !== undefined) {
            coreMetrics.value[1].value = updateData.totalHospitals
            allDataCache.value.coreMetrics.totalHospitals = updateData.totalHospitals
          }
          if (updateData.totalDoctors !== undefined) {
            coreMetrics.value[2].value = updateData.totalDoctors
            allDataCache.value.coreMetrics.totalDoctors = updateData.totalDoctors
          }
          hasChanges = true
          console.log('✅ 核心指标数据已更新')
        }
        break
        
      default:
        console.log('❓ 未知的更新类型:', updateType)
    }
    
    // 更新统计信息
    updateStats.value.totalUpdates++
    updateStats.value.lastUpdateTime = new Date()
    updateStats.value.updateHistory.push({
      type: updateType,
      hasChanges,
      timestamp: new Date()
    })
    
    // 保持历史记录在最近50条
    if (updateStats.value.updateHistory.length > 50) {
      updateStats.value.updateHistory.shift()
    }
    
    if (hasChanges) {
      updateStats.value.skippedUpdates = 0 // 重置跳过计数
      const processingTime = Date.now() - startTime
      console.log(`🎉 数据更新完成，界面将自动刷新 (耗时: ${processingTime}ms)`)
    } else {
      updateStats.value.skippedUpdates++
      console.log(`ℹ️ 数据无变化，无需更新界面 (已跳过 ${updateStats.value.skippedUpdates} 次)`)
    }
    
    // 每10次更新显示一次统计信息
    if (updateStats.value.totalUpdates % 10 === 0) {
      console.log('📊 更新统计:', {
        总更新次数: updateStats.value.totalUpdates,
        跳过次数: updateStats.value.skippedUpdates,
        跳过率: `${((updateStats.value.skippedUpdates / updateStats.value.totalUpdates) * 100).toFixed(1)}%`,
        最后更新: updateStats.value.lastUpdateTime?.toLocaleTimeString()
      })
    }
    
  } catch (error) {
    console.error('❌ 处理实时数据更新失败:', error)
  }
}

// 从医生数据生成专业分布
const generateDoctorSpecialtiesFromDoctors = (doctors: any[]): DoctorSpecialtyItem[] => {
  const specialtyCount: { [key: string]: number } = {}
  
  doctors.forEach((doctor: any) => {
    if (doctor.specialties && doctor.specialties.length > 0) {
      doctor.specialties.forEach((specialty: string) => {
        specialtyCount[specialty] = (specialtyCount[specialty] || 0) + 1
      })
    } else {
      const specialty = doctor.category || '其他'
      specialtyCount[specialty] = (specialtyCount[specialty] || 0) + 1
    }
  })
  
  const totalDoctors = doctors.length
  
  // 只显示前6个主要专业，其他合并为"其他"
  const sortedSpecialties = Object.entries(specialtyCount)
    .map(([specialty, count]) => ({
      specialty,
      count: count as number,
      percentage: totalDoctors > 0 ? ((count as number / totalDoctors) * 100).toFixed(1) : '0.0'
    }))
    .sort((a, b) => b.count - a.count)
  
  const topSpecialties = sortedSpecialties.slice(0, 6)
  const otherSpecialties = sortedSpecialties.slice(6)
  
  // 计算"其他"的总数
  const otherCount = otherSpecialties.reduce((sum, item) => sum + item.count, 0)
  const otherPercentage = totalDoctors > 0 ? ((otherCount / totalDoctors) * 100).toFixed(1) : '0.0'
  
  return [
    ...topSpecialties,
    ...(otherCount > 0 ? [{
      specialty: '其他',
      count: otherCount,
      percentage: otherPercentage
    }] : [])
  ]
}

// 从医院数据生成医院分布
const generateHospitalDistributionFromHospitals = (hospitals: any[]): HospitalDistributionItem[] => {
  console.log('🏥 原始医院数据:', hospitals)
  const provinceMap: { [key: string]: any } = {}
  
  hospitals.forEach((hospital: any) => {
    console.log('🏥 处理医院:', { name: hospital.name, city: hospital.city, province: hospital.province })
    // 使用省份作为分组键，如果没有省份则使用城市
    const province = hospital.province || hospital.city || '未知省份'
    if (!provinceMap[province]) {
      provinceMap[province] = {
        name: province,
        city: hospital.city || province,
        value: 0,
        hospitals: [] as any[],
        avgRating: 0,
        totalRating: 0
      }
    }
    
    provinceMap[province].value += 1
    provinceMap[province].hospitals.push({
      name: hospital.name,
      rating: hospital.rating || 0,
      address: hospital.location,
      category: hospital.category,
      isHot: hospital.isHot
    })
    provinceMap[province].totalRating += hospital.rating || 0
  })
  
  const result = Object.values(provinceMap).map((province: any) => ({
    name: province.name,
    city: province.city,
    value: province.value,
    hospitals: province.hospitals,
    avgRating: province.value > 0 ? (province.totalRating / province.value) : 0
  }))
  
  console.log('🏥 生成的医院分布数据:', result)
  return result
}

// 从产品数据生成价格分析
const generatePriceAnalysisFromProducts = (products: any[]): any[] => {
  const priceRanges = [
    { name: '500-1000', min: 500, max: 1000, color: '#00ffff' },
    { name: '1000-2000', min: 1000, max: 2000, color: '#ff00ff' },
    { name: '2000-3000', min: 2000, max: 3000, color: '#ffff00' },
    { name: '3000-5000', min: 3000, max: 5000, color: '#00ff00' },
    { name: '5000+', min: 5000, max: Infinity, color: '#ff6600' }
  ]
  
  return priceRanges.map(range => {
    const count = products.filter(p => p.price >= range.min && p.price < range.max).length
    return {
      name: range.name,
      value: count,
      color: range.color
    }
  })
}

// 更新医院统计信息
const updateHospitalStats = () => {
  if (hospitalDistribution.value.length > 0) {
    hospitalStats.totalCities = hospitalDistribution.value.length
    hospitalStats.maxHospitals = Math.max(...hospitalDistribution.value.map(item => item.value))
    hospitalStats.avgRating = Number((hospitalDistribution.value.reduce((sum, item) => sum + item.avgRating, 0) / hospitalDistribution.value.length).toFixed(1))
  }
}

// 处理省份点击
const handleProvinceClick = async (data: { province: string; provinceData: any }) => {
  console.log('省份点击事件触发:', data.province, data.provinceData)
  
  // 立即更新UI状态，让用户看到响应
  selectedCity.value = data.province
  
  // 显示加载状态
  console.log('🔄 正在获取省份数据...')
  
  // 只使用Socket.IO请求省份数据
  if (socket.value && socketConnected.value) {
    requestProvinceData(data.province)
  } else {
    console.warn('⚠️ Socket.IO未连接，无法获取省份数据')
    ElMessage.warning('Socket.IO未连接，请检查网络连接')
  }
}

// 处理省份悬停 - 显示省份数据预览
const handleProvinceHover = (data: { province: string; provinceData: any }) => {
  console.log('省份悬停事件触发:', data.province, data.provinceData)
  
  // 可以在这里显示悬停提示，比如显示该省份的医院数量
  if (data.provinceData && data.provinceData.hospitals) {
    const hospitalCount = data.provinceData.hospitals.length
    console.log(`${data.province}有${hospitalCount}家医院`)
  }
}

// 处理省份离开（可选，用于清除选中状态）
const handleProvinceLeave = () => {
  // 注意：这里不自动清除选中状态，让用户主动点击其他省份或"全国"按钮来切换
  console.log('省份离开，保持当前选中状态')
}

// 处理地图空白区域点击 - 恢复全国数据
const handleMapBlankClick = () => {
  console.log('地图空白区域点击，恢复全国数据')
  resetToNationalData()
}

// 添加返回全国数据的功能
const resetToNationalData = () => {
  selectedCity.value = null
  console.log('返回全国数据')
  
  // 恢复全局数据
  cityFilteredData.value = {
    products: [],
    doctors: [],
    hospitals: [],
    priceAnalysis: [],
    coreMetrics: {
      totalProducts: 0,
      totalHospitals: 0,
      totalDoctors: 0
    }
  }
}

// 初始化价格分析图表
const initPriceChart = () => {
  if (!priceChartRef.value) return
  
  console.log('📊 初始化价格分析图表，数据:', priceAnalysisData.value)
  
  // 销毁旧实例
  if (priceChart) {
    priceChart.dispose()
  }
  
  priceChart = echarts.init(priceChartRef.value)
  
  // 检查数据是否为空
  if (!priceAnalysisData.value || priceAnalysisData.value.length === 0) {
    console.log('📊 价格分析数据为空，显示空状态')
    return
  }
  
  const option = {
    backgroundColor: 'transparent',
    grid: {
      left: '5%',
      right: '5%',
      bottom: '15%',
      top: '5%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: priceAnalysisData.value.map(item => item.name),
      axisLine: {
        lineStyle: { color: '#64ffda' }
      },
      axisLabel: {
        color: '#e6e6e6',
        fontSize: 12
      }
    },
    yAxis: {
      type: 'value',
      axisLine: {
        lineStyle: { color: '#64ffda' }
      },
      axisLabel: {
        color: '#e6e6e6',
        fontSize: 12
      },
      splitLine: {
        lineStyle: { color: 'rgba(100, 255, 218, 0.1)' }
      }
    },
    series: [{
      data: priceAnalysisData.value.map(item => ({
        value: item.value,
        itemStyle: { color: item.color }
      })),
      type: 'bar',
      barWidth: '60%',
      itemStyle: {
        borderRadius: [4, 4, 0, 0],
        shadowBlur: 10,
        shadowColor: 'rgba(0, 0, 0, 0.3)'
      }
    }],
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(17, 34, 64, 0.9)',
      borderColor: '#64ffda',
      borderWidth: 1,
      textStyle: { color: '#e6e6e6' }
    }
  }
  
  priceChart.setOption(option)
}

// 初始化医生专业分布图表
const initDoctorChart = () => {
  if (!doctorChartRef.value) return
  
  console.log('👨‍⚕️ 初始化医生专业分布图表，数据:', displayDoctorSpecialtyData.value)
  
  // 销毁旧实例
  if (doctorChart) {
    doctorChart.dispose()
  }
  
  doctorChart = echarts.init(doctorChartRef.value)
  
  // 检查数据是否为空
  if (!displayDoctorSpecialtyData.value || displayDoctorSpecialtyData.value.length === 0) {
    console.log('👨‍⚕️ 医生专业分布数据为空，显示空状态')
    return
  }
  
  const defaultColors = [
    '#ff4757', '#4fc3f7', '#ab47bc', '#66bb6a', '#ffa726', '#ef5350', '#26c6da', '#ff6b35',
    '#9c27b0', '#00bcd4', '#e91e63', '#3f51b5', '#795548', '#607d8b', '#ff9800', '#8bc34a',
    '#f44336', '#2196f3', '#ff5722', '#4caf50', '#ffc107', '#9e9e9e', '#673ab7', '#e57373'
  ]
  
  const option = {
    backgroundColor: 'transparent',
    legend: {
      orient: 'vertical',
      right: '5%',
      top: 'center',
      bottom: '10%',
      textStyle: { color: '#e6e6e6', fontSize: 11 },
      itemWidth: 10,
      itemHeight: 10,
      itemGap: 8,
      formatter: (name: string) => {
        // 限制图例文字长度，避免过长
        return name.length > 6 ? name.substring(0, 6) + '...' : name
      }
    },
    series: [{
      name: '',
      type: 'pie',
      radius: ['35%', '75%'],
      center: ['40%', '50%'],
      data: displayDoctorSpecialtyData.value.map((item, index) => ({
        name: item.name,
        value: item.value,
        itemStyle: {
          color: item.color || defaultColors[index % defaultColors.length],
          borderColor: 'rgba(17, 34, 64, 0.8)',
          borderWidth: 2,
          shadowBlur: 10,
          shadowColor: 'rgba(0, 0, 0, 0.3)'
        }
      })),
      label: {
        show: false, // 关闭饼图上的标签，避免重叠
        position: 'outside',
        formatter: '{b}',
        fontSize: 10,
        color: '#e6e6e6'
      },
      labelLine: {
        show: false // 关闭标签线
      },
      emphasis: {
        label: {
        show: true,
          fontSize: 12,
          fontWeight: 'bold'
        },
        labelLine: {
          show: true,
          lineStyle: { color: 'rgba(100, 255, 218, 0.6)' }
        }
      }
    }],
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(17, 34, 64, 0.9)',
      borderColor: '#64ffda',
      borderWidth: 1,
      textStyle: { color: '#e6e6e6' },
      formatter: (params: any) => {
        return `
          <div style="padding: 8px;">
            <div style="font-size: 14px; color: #64ffda; margin-bottom: 4px;">${params.name}</div>
            <div style="font-size: 16px; color: #06b6d4; font-weight: bold;">${params.percent}%</div>
            <div style="font-size: 12px; color: #e6e6e6; margin-top: 2px;">数量: ${params.value}</div>
          </div>
        `
      }
    }
  }
  
  doctorChart.setOption(option)
}

// 初始化趋势图表
const initTrendChart = () => {
  if (!trendChartRef.value) return
  
  console.log('📈 初始化趋势图表，数据:', trendDataForChart.value)
  
  // 销毁旧实例
  if (trendChart) {
    trendChart.dispose()
  }
  
  trendChart = echarts.init(trendChartRef.value)
  
  // 检查数据是否为空
  if (!trendDataForChart.value || trendDataForChart.value.length === 0) {
    console.log('📈 趋势数据为空，显示空状态')
    return
  }
  
  // 月份数据
  const months = ['7月', '8月', '9月', '10月', '11月']
  
  // 创建折线图数据
  const seriesData = trendDataForChart.value.map(item => ({
    name: item.name,
    type: 'line',
    data: item.data || [0, 0, 0, 0, 0], // 使用原始数据或默认值
    smooth: true,
    lineStyle: { color: item.color, width: 3 },
    itemStyle: { color: item.color },
    areaStyle: {
      color: {
        type: 'linear',
        x: 0, y: 0, x2: 0, y2: 1,
        colorStops: [
          { offset: 0, color: item.color + '40' },
          { offset: 1, color: item.color + '10' }
        ]
      }
    }
  }))
  
  const option = {
    backgroundColor: 'transparent',
    grid: {
      left: '5%',
      right: '5%',
      bottom: '15%',
      top: '5%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: months,
      axisLine: {
        lineStyle: { color: '#64ffda' }
      },
      axisLabel: {
        color: '#e6e6e6',
        fontSize: 12
      }
    },
    yAxis: {
      type: 'value',
      axisLine: {
        lineStyle: { color: '#64ffda' }
      },
      axisLabel: {
        color: '#e6e6e6',
        fontSize: 12
      },
      splitLine: {
        lineStyle: { color: 'rgba(100, 255, 218, 0.1)' }
      }
    },
    series: seriesData,
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(17, 34, 64, 0.9)',
      borderColor: '#64ffda',
      borderWidth: 1,
      textStyle: { color: '#e6e6e6' },
      formatter: (params: any) => {
        let result = `<div style="padding: 8px;"><div style="font-size: 14px; color: #64ffda; margin-bottom: 4px;">${params[0].axisValue}</div>`
        params.forEach((param: any) => {
          result += `<div style="font-size: 12px; color: #e6e6e6; margin-bottom: 2px;">
            <span style="display: inline-block; width: 10px; height: 10px; background: ${param.color}; margin-right: 5px; border-radius: 50%;"></span>
            ${param.seriesName}: ${param.value}
          </div>`
        })
        result += '</div>'
        return result
      }
    },
    legend: {
      show: true,
      top: '5%',
      right: '5%',
      textStyle: { color: '#e6e6e6', fontSize: 12 },
      itemWidth: 12,
      itemHeight: 12
    }
  }
  
  trendChart.setOption(option)
}

// 应用数据到组件
const applyDataToComponents = (data: any) => {
  // 更新缓存
  allDataCache.value = data
  
  // 更新各个组件的数据
  if (data.coreMetrics) {
    coreMetrics.value[0].value = data.coreMetrics.totalProducts || 0
    coreMetrics.value[1].value = data.coreMetrics.totalHospitals || 0
    coreMetrics.value[2].value = data.coreMetrics.totalDoctors || 0
  }
  
  if (data.productTop10) {
    productTop10.value = data.productTop10
  }
  
  if (data.doctorSpecialties) {
    doctorSpecialties.value = data.doctorSpecialties
  }
  
  if (data.hospitalDistribution) {
    console.log('🏥 设置医院分布数据:', data.hospitalDistribution)
    hospitalDistribution.value = data.hospitalDistribution
    updateHospitalStats()
    // 初始加载时也增加计数器
    mapUpdateCounter.value++
    console.log('🗺️ 初始地图更新计数器:', mapUpdateCounter.value)
  }
  
  // 价格分析数据从产品数据生成
  if (data.products && data.products.length > 0) {
    allDataCache.value.priceAnalysis = generatePriceAnalysisFromProducts(data.products)
    console.log('从产品数据生成价格分析:', allDataCache.value.priceAnalysis)
  }
}

// 更新时间信息
const updateTime = () => {
  const now = new Date()
  currentTime.value = now.toLocaleTimeString('zh-CN', { 
    hour12: false,
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
  currentDate.value = now.toLocaleDateString('zh-CN', { 
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
  })
  currentDay.value = now.toLocaleDateString('zh-CN', { weekday: 'long' })
}

// 计算缩放比例 - 完美适配，无白边，保持比例
const calculateScale = () => {
  if (!dashboardRef.value) return
  
  const container = dashboardRef.value
  const windowWidth = window.innerWidth
  const windowHeight = window.innerHeight
  
  // 计算宽高比
  const scaleX = windowWidth / baseWidth
  const scaleY = windowHeight / baseHeight
  
  // 使用较小的缩放比例，确保内容完全显示且不变形
  const newScale = Math.min(scaleX, scaleY)
  
  // 应用缩放，保持完美居中
  scale.value = newScale
  container.style.transform = `translate(-50%, -50%) scale(${newScale})`
  container.style.transformOrigin = 'center center'
  
  // 保持原始尺寸，让transform处理缩放
  container.style.width = `${baseWidth}px`
  container.style.height = `${baseHeight}px`
  
  // 确保容器占满视口，避免白边
  container.style.position = 'absolute'
  container.style.top = '50%'
  container.style.left = '50%'
  
  // 强制设置背景，确保无白边
  forceResetPageStyle()
  
  console.log('🔄 缩放计算:', {
    windowSize: { width: windowWidth, height: windowHeight },
    baseSize: { width: baseWidth, height: baseHeight },
    scaleX: scaleX.toFixed(3),
    scaleY: scaleY.toFixed(3),
    finalScale: newScale.toFixed(3),
    aspectRatio: (windowWidth / windowHeight).toFixed(3)
  })
}

// 防抖处理
let resizeTimer: number | null = null

// 处理窗口大小变化 - 优化防抖和重绘
const handleResize = () => {
  if (resizeTimer) {
    clearTimeout(resizeTimer)
  }
  
  resizeTimer = setTimeout(() => {
    // 强制重置页面样式，确保无白边
    forceResetPageStyle()
    
    // 重新计算缩放
    calculateScale()
    
    // 延迟重绘图表，确保容器尺寸已更新
    setTimeout(() => {
      if (priceChart) {
        priceChart.resize()
        priceChart.setOption(priceChart.getOption(), true)
      }
      if (doctorChart) {
        doctorChart.resize()
        doctorChart.setOption(doctorChart.getOption(), true)
      }
      if (trendChart) {
        trendChart.resize()
        trendChart.setOption(trendChart.getOption(), true)
      }
    }, 100) // 增加延迟时间，确保缩放完成后再重绘
  }, 100) // 减少防抖时间，提高响应速度
}

// 处理键盘事件
const handleKeydown = (event: KeyboardEvent) => {
  // 防止页面缩放
  if (event.ctrlKey && (event.key === '+' || event.key === '-' || event.key === '0')) {
    event.preventDefault()
  }
}

// 模拟加载进度
const simulateLoadingProgress = () => {
  let currentStep = 0
  const progressInterval = setInterval(() => {
    if (currentStep < loadingSteps.value.length) {
      loadingProgress.value = loadingSteps.value[currentStep].progress
      currentStep++
    } else {
      clearInterval(progressInterval)
      // 加载完成
      setTimeout(() => {
    loading.value = false
        dataLoaded.value = true
      }, 500)
  }
  }, 800) // 每800ms更新一次进度
}

// 强制重置页面样式，确保无白边
const forceResetPageStyle = () => {
  // 重置body和html
  document.body.style.margin = '0'
  document.body.style.padding = '0'
  document.body.style.overflow = 'hidden'
  document.body.style.backgroundColor = '#000'
  document.body.style.width = '100vw'
  document.body.style.height = '100vh'
  document.body.style.position = 'fixed'
  document.body.style.top = '0'
  document.body.style.left = '0'
  document.body.style.right = '0'
  document.body.style.bottom = '0'
  document.body.style.boxSizing = 'border-box'
  
  // 重置html
  document.documentElement.style.margin = '0'
  document.documentElement.style.padding = '0'
  document.documentElement.style.overflow = 'hidden'
  document.documentElement.style.backgroundColor = '#000'
  document.documentElement.style.width = '100%'
  document.documentElement.style.height = '100%'
  document.documentElement.style.boxSizing = 'border-box'
  
  // 重置#app
  const app = document.getElementById('app')
  if (app) {
    app.style.margin = '0'
    app.style.padding = '0'
    app.style.overflow = 'hidden'
    app.style.backgroundColor = '#000'
    app.style.width = '100%'
    app.style.height = '100%'
    app.style.boxSizing = 'border-box'
  }
  
  // 确保所有元素都使用border-box
  const allElements = document.querySelectorAll('*')
  allElements.forEach(el => {
    if (el instanceof HTMLElement) {
      el.style.boxSizing = 'border-box'
    }
  })
  
  console.log('🔄 页面样式强制重置完成')
}

// 初始化自适应缩放
const initAdaptiveScaling = () => {
  // 强制重置页面样式
  forceResetPageStyle()
  
  // 立即计算一次缩放
  calculateScale()
  
  // 使用requestAnimationFrame确保DOM已渲染
  requestAnimationFrame(() => {
    forceResetPageStyle()
    calculateScale()
  })
  
  // 延迟计算，确保所有内容已加载
  setTimeout(() => {
    forceResetPageStyle()
    calculateScale()
  }, 1000)
  
  // 监听窗口大小变化
  window.addEventListener('resize', handleResize)
  window.addEventListener('keydown', handleKeydown)
  
  // 监听页面可见性变化
  document.addEventListener('visibilitychange', () => {
    if (!document.hidden) {
      forceResetPageStyle()
      calculateScale()
    }
  })
  
  // 监听全屏变化
  document.addEventListener('fullscreenchange', () => {
    setTimeout(() => {
      forceResetPageStyle()
      calculateScale()
    }, 100)
  })
  
  // 监听窗口焦点变化
  window.addEventListener('focus', () => {
    setTimeout(() => {
      forceResetPageStyle()
      calculateScale()
    }, 50)
  })
  
  // 监听设备方向变化
  window.addEventListener('orientationchange', () => {
    setTimeout(() => {
      forceResetPageStyle()
      calculateScale()
    }, 200)
  })
  
  // 监听窗口移动
  window.addEventListener('move', () => {
    setTimeout(() => {
      forceResetPageStyle()
      calculateScale()
    }, 50)
  })
  
  console.log('🎯 自适应缩放初始化完成')
}

// 组件挂载
onMounted(async () => {
  // 启动加载进度模拟
  simulateLoadingProgress()
  
  // 异步加载数据
  setTimeout(async () => {
    try {
      // 只使用Socket.IO
      console.log('🚀 初始化Socket.IO连接...')
      initSocketIO()
    } catch (error) {
      console.error('数据加载失败:', error)
    }
  }, 1000) // 延迟1秒开始加载数据
  
  // 初始化自适应缩放
  initAdaptiveScaling()
  
  // 初始化时间
  updateTime()
  setInterval(updateTime, 1000)
  
  // 监听页面可见性变化
  document.addEventListener('visibilitychange', () => {
    if (!document.hidden) {
      forceResetPageStyle()
      calculateScale()
    }
  })
  
  // 初始化图表 - 延迟初始化确保数据准备好
  setTimeout(() => {
    nextTick(() => {
      console.log('🚀 开始初始化图表...')
      initPriceChart()
      initDoctorChart()
      initTrendChart()
    })
  }, 2000) // 延迟2秒确保Socket.IO数据加载完成
})

// 监听数据变化，重新渲染图表
watch(priceAnalysisData, (newData) => {
  console.log('📊 价格分析数据变化，重新渲染图表:', newData)
  if (newData && newData.length > 0) {
    nextTick(() => {
      initPriceChart()
    })
  }
}, { deep: true, immediate: true })

watch(displayDoctorSpecialtyData, (newData) => {
  console.log('👨‍⚕️ 医生专业分布数据变化，重新渲染图表:', newData)
  if (newData && newData.length > 0) {
    nextTick(() => {
      initDoctorChart()
    })
  }
}, { deep: true, immediate: true })

watch(trendDataForChart, (newData) => {
  console.log('📈 趋势数据变化，重新渲染图表:', newData)
  if (newData && newData.length > 0) {
    nextTick(() => {
      initTrendChart()
    })
  }
}, { deep: true, immediate: true })

// 监听排行榜数据变化，启动自动滚动
watch(displayProducts, (newProducts) => {
  if (newProducts && newProducts.length > 0) {
    // 延迟启动自动滚动，确保DOM已更新
    nextTick(() => {
      setTimeout(() => {
        startAutoScroll()
      }, 1000) // 1秒后开始自动滚动
    })
  }
}, { immediate: true })

// 组件卸载
onUnmounted(() => {
  // 停止自动滚动
  stopAutoScroll()
  
  // 断开Socket.IO连接
  if (socket.value) {
    console.log('🔌 断开Socket.IO连接')
    socket.value.emit('leave-dashboard-updates', {
      userId: 'dashboard-user-' + Date.now()
    })
    socket.value.disconnect()
  }
  
  
  // 清理事件监听器
  window.removeEventListener('resize', handleResize)
  window.removeEventListener('keydown', handleKeydown)
  
  // 清理定时器
  if (resizeTimer) {
    clearTimeout(resizeTimer)
  }
})
</script>

<style lang="scss" scoped>
// 全局重置，确保全屏显示
:global(body) {
  margin: 0 !important;
  padding: 0 !important;
  overflow: hidden !important;
  width: 100vw !important;
  height: 100vh !important;
  background: #000 !important;
  box-sizing: border-box !important;
}

:global(html) {
  margin: 0 !important;
  padding: 0 !important;
  overflow: hidden !important;
  width: 100vw !important;
  height: 100vh !important;
  background: #000 !important;
  box-sizing: border-box !important;
}

// 确保根容器也占满全屏
:global(#app) {
  width: 100vw !important;
  height: 100vh !important;
  overflow: hidden !important;
  background: #000 !important;
  box-sizing: border-box !important;
}

// 重置默认样式，确保没有白边
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: #000;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  box-sizing: border-box;
}

#app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: #000;
  box-sizing: border-box;
}

// 外层容器 - 用于自适应缩放
.dashboard-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: linear-gradient(135deg, #0a0e27 0%, #1a1f3a 50%, #0f1419 100%);
  overflow: hidden;
  margin: 0;
  padding: 0;
  z-index: 1000;
  min-width: 100vw;
  min-height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  box-sizing: border-box;
  
  // 防止浏览器默认缩放
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  
  // 防止双击缩放
  touch-action: manipulation;
  
  // 确保完全覆盖，无白边
  &::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: linear-gradient(135deg, #0a0e27 0%, #1a1f3a 50%, #0f1419 100%);
    z-index: -1;
  }
}

// 大屏容器 - 固定尺寸，通过transform整体缩放
.dashboard-container {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: transparent;
  color: #fff;
  transform-origin: center center;
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  transform: translate(-50%, -50%) scale(1);
  will-change: transform;
  
  // 确保字体渲染质量
  font-smooth: always;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  
  // 防止布局抖动和崩塌
  backface-visibility: hidden;
  perspective: 1000px;
  
  // 强制保持原始比例，防止崩塌
  min-width: 1920px;
  min-height: 1080px;
  max-width: 1920px;
  max-height: 1080px;
  
  // 确保所有子元素正确缩放
  * {
    transform-origin: center center;
    backface-visibility: hidden;
    box-sizing: border-box;
  }
}

.dashboard-header {
  height: 120px;
  padding: 0;
  flex-shrink: 0;
  background: 
    linear-gradient(135deg, rgba(0, 0, 0, 0.6), rgba(26, 26, 46, 0.8)),
    radial-gradient(ellipse at 50% 0%, rgba(0, 255, 255, 0.1) 0%, transparent 70%);
  backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(0, 255, 255, 0.3);
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;

  // 顶部通知栏
  .notification-bar {
    height: 35px;
    background: linear-gradient(90deg, rgba(0, 255, 255, 0.08), transparent);
    border-bottom: 1px solid rgba(0, 255, 255, 0.15);
    display: flex;
    align-items: center;
    padding: 0 25px;
    overflow: hidden;
    
    .notification-icon {
      width: 18px;
      height: 18px;
      color: #fff;
      font-size: 16px;
      margin-right: 12px;
      filter: drop-shadow(0 0 4px rgba(0, 255, 255, 0.6));
    }
    
    .notification-text {
      flex: 1;
      
      .notification-content {
        color: #fff;
        font-size: 13px;
        font-weight: 400;
        white-space: nowrap;
        animation: scrollText 20s linear infinite;
        text-shadow: 0 0 6px rgba(0, 255, 255, 0.4);
      }
    }
  }
  
  // 主要内容区域
  .header-main {
    flex: 1;
      display: flex;
      align-items: center;
    justify-content: space-between;
    padding: 0 30px;
  }

  // 左侧状态信息
  .header-left {
    display: flex;
    align-items: center;
    gap: 12px;
    position: relative;
    
    .status-icon {
      width: 24px;
      height: 24px;
      color: #fff;
      font-size: 18px;
    }
    
    .status-text {
      color: #fff;
      font-size: 14px;
      font-weight: 500;
    }
    
    // 左侧装饰几何
    .left-decoration {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      pointer-events: none;
      
      .angular-line {
        position: absolute;
        background: linear-gradient(45deg, rgba(0, 255, 255, 0.6), transparent);
        box-shadow: 0 0 8px rgba(0, 255, 255, 0.4);
        
        &.line-1 {
          top: 20px;
          left: -10px;
          width: 30px;
          height: 2px;
          transform: rotate(-30deg);
          animation: angularGlow 3s ease-in-out infinite alternate;
        }
        
        &.line-2 {
          bottom: 15px;
          left: -5px;
          width: 25px;
          height: 1px;
          transform: rotate(45deg);
          animation: angularGlow 3s ease-in-out infinite alternate 1.5s;
        }
      }
      
      .geometric-shape {
        position: absolute;
        border: 1px solid rgba(0, 255, 255, 0.4);
        box-shadow: 0 0 6px rgba(0, 255, 255, 0.3);
        
        &.shape-1 {
          top: 10px;
          right: -15px;
          width: 8px;
          height: 8px;
          transform: rotate(45deg);
          animation: shapePulse 2s ease-in-out infinite;
        }
        
        &.shape-2 {
          bottom: 8px;
          right: -20px;
          width: 6px;
          height: 6px;
          transform: rotate(45deg);
          animation: shapePulse 2s ease-in-out infinite 1s;
        }
      }
    }
  }

  // 中央标题面板
  .header-center {
    flex: 1;
    display: flex;
    justify-content: center;
    
    .title-panel {
      position: relative;
      background: 
        linear-gradient(135deg, rgba(0, 0, 0, 0.8), rgba(26, 26, 46, 0.9)),
        linear-gradient(45deg, rgba(0, 255, 255, 0.1) 0%, transparent 50%, rgba(138, 43, 226, 0.05) 100%);
      border: none;
      border-radius: 16px;
      padding: 24px 48px;
      box-shadow: 
        0 12px 40px rgba(0, 0, 0, 0.6),
        0 0 30px rgba(0, 255, 255, 0.3),
        0 0 60px rgba(0, 255, 255, 0.1),
        inset 0 1px 0 rgba(255, 255, 255, 0.2);
      backdrop-filter: blur(25px) saturate(1.2);
      animation: panelGlow 3s ease-in-out infinite alternate;
      overflow: hidden;
      
      .title-background {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 16px;
        overflow: hidden;
        
        .title-glow {
          position: absolute;
          top: -50%;
          left: -50%;
          right: -50%;
          bottom: -50%;
          background: radial-gradient(circle, rgba(0, 255, 255, 0.1) 0%, transparent 70%);
          animation: rotateGlow 8s linear infinite;
        }
        
        .title-pattern {
          position: absolute;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background-image: 
            linear-gradient(45deg, rgba(0, 255, 255, 0.03) 25%, transparent 25%),
            linear-gradient(-45deg, rgba(0, 255, 255, 0.03) 25%, transparent 25%);
          background-size: 20px 20px;
          opacity: 0.4;
        }
      }
      
      // 几何装饰线条
      .geometric-decoration {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        pointer-events: none;
        
        // 左侧3条平行斜线
        .left-diagonal-lines {
          position: absolute;
          left: -40px;
          top: 50%;
          transform: translateY(-50%);
          
          .diagonal-line {
            position: absolute;
            width: 25px;
            height: 2px;
            background: linear-gradient(90deg, 
              rgba(0, 255, 255, 0.8), 
              rgba(0, 255, 255, 0.4), 
              transparent);
            box-shadow: 0 0 6px rgba(0, 255, 255, 0.5);
            transform: rotate(-15deg);
            animation: diagonalGlow 3s ease-in-out infinite alternate;
            
            &.line-1 {
              top: -8px;
              animation-delay: 0s;
            }
            
            &.line-2 {
              top: 0px;
              animation-delay: 0.5s;
            }
            
            &.line-3 {
              top: 8px;
              animation-delay: 1s;
            }
          }
        }
        
        // 右侧3条平行斜线
        .right-diagonal-lines {
          position: absolute;
          right: -40px;
          top: 50%;
          transform: translateY(-50%);
          
          .diagonal-line {
            position: absolute;
            width: 25px;
            height: 2px;
            background: linear-gradient(90deg, 
              transparent, 
              rgba(0, 255, 255, 0.4), 
              rgba(0, 255, 255, 0.8));
            box-shadow: 0 0 6px rgba(0, 255, 255, 0.5);
            transform: rotate(15deg);
            animation: diagonalGlow 3s ease-in-out infinite alternate;
            
            &.line-1 {
              top: -8px;
              animation-delay: 0s;
            }
            
            &.line-2 {
              top: 0px;
              animation-delay: 0.5s;
            }
            
            &.line-3 {
              top: 8px;
              animation-delay: 1s;
            }
          }
        }
        
        // 底部水平连接线
        .bottom-connector-line {
          position: absolute;
          bottom: 15px;
          left: -30px;
          right: -30px;
          height: 1px;
          background: linear-gradient(90deg, 
            transparent, 
            rgba(0, 255, 255, 0.3), 
            rgba(0, 255, 255, 0.6), 
            rgba(0, 255, 255, 0.3), 
            transparent);
          box-shadow: 0 0 4px rgba(0, 255, 255, 0.4);
          animation: connectorGlow 4s ease-in-out infinite alternate;
        }
      }
    }
  }

  .dashboard-title {
        font-size: 30px;
        font-weight: 700;
        margin: 0 0 8px 0;
        color: #fff;
        text-align: center;
        text-shadow: 
          0 0 8px rgba(0, 255, 255, 0.8),
          0 0 16px rgba(0, 255, 255, 0.6),
          0 0 24px rgba(0, 255, 255, 0.4),
          0 0 32px rgba(0, 255, 255, 0.2);
        letter-spacing: 2px;
        animation: titleGlow 3s ease-in-out infinite alternate;
        filter: drop-shadow(0 0 8px rgba(0, 255, 255, 0.6));
      }
      
      .title-subtitle {
        font-size: 14px;
        color: rgba(255, 255, 255, 0.8);
        text-align: center;
        font-weight: 300;
        letter-spacing: 1px;
      }
      
      // 装饰线条
      .decorative-lines {
        position: absolute;
        top: 50%;
        left: 0;
        right: 0;
        height: 2px;
        transform: translateY(-50%);
        
        .line {
          position: absolute;
          height: 2px;
          background: linear-gradient(90deg, 
            transparent, 
            rgba(0, 255, 255, 0.6), 
            rgba(0, 255, 255, 0.8), 
            rgba(0, 255, 255, 0.6), 
            transparent);
          box-shadow: 0 0 6px rgba(0, 255, 255, 0.4);
          animation: lineGlow 3s ease-in-out infinite alternate;
          
          &.line-left {
            left: -35px;
            width: 25px;
            transform: rotate(-12deg);
            animation-delay: 0s;
          }
          
          &.line-right {
            right: -35px;
            width: 25px;
            transform: rotate(12deg);
            animation-delay: 1.5s;
          }
        }
        
        .diagonal-line {
          position: absolute;
          background: linear-gradient(45deg, 
            transparent, 
            rgba(0, 255, 255, 0.6), 
            rgba(0, 255, 255, 0.8), 
            rgba(0, 255, 255, 0.6), 
            transparent);
          box-shadow: 0 0 8px rgba(0, 255, 255, 0.4);
          animation: diagonalGlow 4s ease-in-out infinite alternate;
          
          &.diagonal-1 {
            top: 15px;
            left: -20px;
            width: 40px;
            height: 2px;
            transform: rotate(-25deg);
            animation-delay: 0s;
          }
          
          &.diagonal-2 {
            bottom: 15px;
            right: -20px;
            width: 40px;
            height: 2px;
            transform: rotate(25deg);
            animation-delay: 2s;
          }
        }
      }
    }
  

  // 右侧时间和操作
  .header-right {
    display: flex;
    align-items: center;
    gap: 20px;
    position: relative;
    
    .time-info {
      display: flex;
      align-items: center;
      gap: 8px;
      
      .current-time {
        font-size: 18px;
    font-weight: bold;
        color: #fff;
        text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
      }
      
      .time-separator {
        color: rgba(0, 255, 255, 0.6);
        font-size: 16px;
        font-weight: 300;
      }
      
      .current-date,
      .current-day {
        font-size: 12px;
        color: rgba(255, 255, 255, 0.8);
      }
  }

    
    // 右侧装饰几何
    .right-decoration {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      pointer-events: none;
      
      .angular-line {
        position: absolute;
        background: linear-gradient(-45deg, rgba(0, 255, 255, 0.6), transparent);
        box-shadow: 0 0 8px rgba(0, 255, 255, 0.4);
        
        &.line-3 {
          top: 15px;
          right: -10px;
          width: 35px;
          height: 2px;
          transform: rotate(30deg);
          animation: angularGlow 3s ease-in-out infinite alternate 0.5s;
        }
        
        &.line-4 {
          bottom: 20px;
          right: -5px;
          width: 30px;
          height: 1px;
          transform: rotate(-45deg);
          animation: angularGlow 3s ease-in-out infinite alternate 2s;
        }
      }
      
      .geometric-shape {
        position: absolute;
        border: 1px solid rgba(0, 255, 255, 0.4);
        box-shadow: 0 0 6px rgba(0, 255, 255, 0.3);
        
        &.shape-3 {
          top: 5px;
          left: -25px;
          width: 10px;
          height: 10px;
          transform: rotate(45deg);
          animation: shapePulse 2s ease-in-out infinite 0.5s;
        }
      }
    }
  }

  // 底部装饰区域
  .header-decoration {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 12px;
    overflow: hidden;
    
    .decoration-line {
      position: absolute;
      top: 6px;
      left: 0;
      right: 0;
      height: 1px;
      background: linear-gradient(90deg, 
        transparent, 
        rgba(0, 255, 255, 0.4), 
        rgba(0, 255, 255, 0.8), 
        rgba(0, 255, 255, 0.4), 
        transparent);
      box-shadow: 0 0 4px rgba(0, 255, 255, 0.3);
    }
    
    .decoration-nodes {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 100%;
      
      .node {
        position: absolute;
        width: 4px;
        height: 4px;
        background: radial-gradient(circle, rgba(255, 255, 0, 0.9), rgba(255, 255, 0, 0.5));
        border-radius: 50%;
        box-shadow: 
          0 0 6px rgba(255, 255, 0, 0.6),
          0 0 12px rgba(255, 255, 0, 0.3);
        animation: nodePulse 2s ease-in-out infinite;
        
        &:nth-child(1) {
          top: 4px;
          left: 20%;
          animation-delay: 0s;
        }
        
        &:nth-child(2) {
          top: 4px;
          left: 50%;
          animation-delay: 0.7s;
        }
        
        &:nth-child(3) {
          top: 4px;
          left: 80%;
          animation-delay: 1.4s;
        }
      }
    }
    
    .decoration-pattern {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 100%;
      
      .pattern-line {
        position: absolute;
        height: 1px;
        background: linear-gradient(90deg, 
          transparent, 
          rgba(0, 255, 255, 0.2), 
          rgba(0, 255, 255, 0.4), 
          rgba(0, 255, 255, 0.2), 
          transparent);
        animation: patternFlow 4s linear infinite;
        
        &:nth-child(1) {
          top: 2px;
          left: 10%;
          width: 15%;
          animation-delay: 0s;
        }
        
        &:nth-child(2) {
          top: 8px;
          left: 60%;
          width: 20%;
          animation-delay: 1.3s;
        }
        
        &:nth-child(3) {
          top: 2px;
          left: 85%;
          width: 10%;
          animation-delay: 2.6s;
        }
      }
    }
  }



// 节点脉冲动画
@keyframes nodePulse {
  0%, 100% {
    opacity: 0.8;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.5);
  }
}

// 面板发光动画
@keyframes panelGlow {
  0% {
    box-shadow: 
      0 8px 32px rgba(0, 0, 0, 0.4),
      0 0 20px rgba(0, 255, 255, 0.2),
      0 0 40px rgba(0, 255, 255, 0.08),
      inset 0 1px 0 rgba(255, 255, 255, 0.15);
  }
  100% {
    box-shadow: 
      0 8px 32px rgba(0, 0, 0, 0.4),
      0 0 25px rgba(0, 255, 255, 0.3),
      0 0 50px rgba(0, 255, 255, 0.12),
      inset 0 1px 0 rgba(255, 255, 255, 0.2);
  }
}

// 标题发光动画
@keyframes titleGlow {
  0% {
    text-shadow: 
      0 0 8px rgba(0, 255, 255, 0.8),
      0 0 16px rgba(0, 255, 255, 0.6),
      0 0 24px rgba(0, 255, 255, 0.4),
      0 0 32px rgba(0, 255, 255, 0.2);
  }
  100% {
    text-shadow: 
      0 0 10px rgba(0, 255, 255, 1),
      0 0 20px rgba(0, 255, 255, 0.8),
      0 0 30px rgba(0, 255, 255, 0.6),
      0 0 40px rgba(0, 255, 255, 0.3);
  }
}

// 线条发光动画
@keyframes lineGlow {
  0% {
    opacity: 0.7;
    box-shadow: 0 0 6px rgba(0, 255, 255, 0.4);
  }
  100% {
    opacity: 1;
    box-shadow: 0 0 10px rgba(0, 255, 255, 0.6);
  }
}

// 文字滚动动画
@keyframes scrollText {
  0% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(-100%);
  }
}

// 旋转发光动画
@keyframes rotateGlow {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

// 图案流动动画
@keyframes patternFlow {
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: translateX(100%);
    opacity: 0;
  }
}

// 角度发光动画
@keyframes angularGlow {
  0% {
    opacity: 0.6;
    box-shadow: 0 0 8px rgba(0, 255, 255, 0.4);
  }
  100% {
    opacity: 1;
    box-shadow: 0 0 12px rgba(0, 255, 255, 0.6);
  }
}

// 形状脉冲动画
@keyframes shapePulse {
  0% {
    transform: rotate(45deg) scale(1);
    opacity: 0.6;
  }
  50% {
    transform: rotate(45deg) scale(1.2);
    opacity: 1;
  }
  100% {
    transform: rotate(45deg) scale(1);
    opacity: 0.6;
  }
}

// 对角发光动画
@keyframes diagonalGlow {
  0% {
    opacity: 0.7;
    box-shadow: 0 0 6px rgba(0, 255, 255, 0.5);
  }
  100% {
    opacity: 1;
    box-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
  }
}

// 连接线发光动画
@keyframes connectorGlow {
  0% {
    opacity: 0.6;
    box-shadow: 0 0 4px rgba(0, 255, 255, 0.4);
  }
  100% {
    opacity: 1;
    box-shadow: 0 0 8px rgba(0, 255, 255, 0.6);
  }
}

// 加载遮罩层样式
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: 
    linear-gradient(135deg, rgba(0, 0, 0, 0.9), rgba(26, 26, 46, 0.95)),
    radial-gradient(ellipse at center, rgba(0, 255, 255, 0.1) 0%, transparent 70%);
  backdrop-filter: blur(20px);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fadeIn 0.5s ease-in-out;
  
  .loading-content {
    text-align: center;
    max-width: 600px;
    padding: 40px;
    
    .loading-animation {
      position: relative;
      margin-bottom: 40px;
      
      .loading-spinner {
        position: relative;
        width: 120px;
        height: 120px;
        margin: 0 auto;
        
        .spinner-ring {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          border: 3px solid transparent;
          border-top: 3px solid rgba(0, 255, 255, 0.8);
          border-radius: 50%;
          animation: spin 2s linear infinite;
          
          &:nth-child(1) {
            animation-delay: 0s;
            border-top-color: rgba(0, 255, 255, 0.8);
          }
          
          &:nth-child(2) {
            animation-delay: 0.3s;
            border-top-color: rgba(138, 43, 226, 0.6);
            width: 80%;
            height: 80%;
            top: 10%;
            left: 10%;
          }
          
          &:nth-child(3) {
            animation-delay: 0.6s;
            border-top-color: rgba(79, 195, 247, 0.4);
            width: 60%;
            height: 60%;
            top: 20%;
            left: 20%;
          }
        }
      }
      
      .loading-particles {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 200px;
        height: 200px;
        
        .particle {
          position: absolute;
          width: 4px;
          height: 4px;
          background: radial-gradient(circle, rgba(0, 255, 255, 0.8), transparent);
          border-radius: 50%;
          animation: particleOrbit 3s linear infinite;
          animation-delay: var(--delay);
          
          &:nth-child(1) { top: 0; left: 50%; }
          &:nth-child(2) { top: 14.6%; left: 85.4%; }
          &:nth-child(3) { top: 50%; left: 100%; }
          &:nth-child(4) { top: 85.4%; left: 85.4%; }
          &:nth-child(5) { top: 100%; left: 50%; }
          &:nth-child(6) { top: 85.4%; left: 14.6%; }
          &:nth-child(7) { top: 50%; left: 0; }
          &:nth-child(8) { top: 14.6%; left: 14.6%; }
        }
      }
    }
    
    .loading-text {
      margin-bottom: 30px;
      
      h3 {
        font-size: 32px;
        font-weight: 700;
        color: #fff;
        margin: 0 0 10px 0;
        text-shadow: 
          0 0 10px rgba(0, 255, 255, 0.8),
          0 0 20px rgba(0, 255, 255, 0.6),
          0 0 30px rgba(0, 255, 255, 0.4);
        animation: titleGlow 2s ease-in-out infinite alternate;
      }
      
      p {
        font-size: 16px;
        color: rgba(255, 255, 255, 0.8);
        margin: 0 0 20px 0;
        font-weight: 300;
      }
      
      .loading-progress {
        display: flex;
        align-items: center;
        gap: 15px;
        justify-content: center;
        
        .progress-bar {
          width: 300px;
          height: 6px;
          background: rgba(255, 255, 255, 0.1);
          border-radius: 3px;
          overflow: hidden;
          position: relative;
          
          .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, 
              rgba(0, 255, 255, 0.8), 
              rgba(138, 43, 226, 0.6), 
              rgba(79, 195, 247, 0.8));
            border-radius: 3px;
            transition: width 0.5s ease;
            box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
            animation: progressGlow 2s ease-in-out infinite alternate;
          }
        }
        
        .progress-text {
          font-size: 14px;
          color: rgba(0, 255, 255, 0.9);
          font-weight: 600;
          min-width: 40px;
        }
      }
    }
    
    .loading-tips {
      display: flex;
      flex-direction: column;
      gap: 12px;
      
      .tip-item {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 16px;
        background: rgba(0, 255, 255, 0.05);
        border: 1px solid rgba(0, 255, 255, 0.2);
        border-radius: 8px;
        color: rgba(255, 255, 255, 0.7);
        font-size: 14px;
        animation: tipFadeIn 0.5s ease-in-out;
        
        .el-icon {
          color: rgba(0, 255, 255, 0.8);
          font-size: 16px;
        }
      }
    }
  }
}

// 加载动画关键帧
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

@keyframes particleOrbit {
  0% {
    transform: rotate(0deg) translateX(100px) rotate(0deg);
    opacity: 0;
  }
  10% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    transform: rotate(360deg) translateX(100px) rotate(-360deg);
    opacity: 0;
  }
}

@keyframes progressGlow {
  0% {
    box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
  }
  100% {
    box-shadow: 0 0 20px rgba(0, 255, 255, 0.8);
  }
}

@keyframes tipFadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

// 状态脉冲动画
@keyframes statusPulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.7;
    transform: scale(1.2);
  }
}


.metrics-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 15px;
  padding: 15px 30px;
  flex-shrink: 0;
  background: rgba(0, 0, 0, 0.1);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  height: 120px; /* 固定高度，防止塌陷 */
  min-height: 120px; /* 最小高度保证 */
  max-height: 120px; /* 最大高度限制 */
  box-sizing: border-box;
  
  /* 确保卡片不会变形 */
  align-items: stretch;
  justify-items: stretch;
  
  /* 确保网格项目填充整个容器 */
  grid-template-rows: 1fr;
  
  /* 防止内容溢出 */
  overflow: hidden;
  
  /* 确保DataCard组件能够正确填充网格 */
  :deep(.data-card) {
    width: 100%;
    height: 100%;
    min-height: 80px;
    max-height: 100px;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
  }
  
  /* 确保DataCard内容能够正确显示 */
  :deep(.data-card .card-header) {
    flex-shrink: 0;
    min-height: 20px;
  }
  
  :deep(.data-card .card-content) {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 40px;
    overflow: hidden;
  }
  
  :deep(.data-card .main-value) {
    flex-shrink: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 36px !important; /* 强制固定字体大小 */
  }
  
  :deep(.data-card .header-title) {
    font-size: 14px !important; /* 强制固定字体大小 */
  }
  
  :deep(.data-card .header-icon) {
    font-size: 16px !important; /* 强制固定字体大小 */
  }
}

.main-content {
  display: grid;
  grid-template-columns: 350px 1fr 350px;
  gap: 20px;
  flex: 1;
  min-height: 0;
  padding: 20px 30px;
  overflow: hidden;
  width: 100%;
  height: 960px; /* 固定高度：1080 - 120(header) = 960px */
  background: rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(5px);
  box-sizing: border-box;
}

.left-panel, .right-panel {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  box-sizing: border-box;
}

.center-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-width: 0;
  overflow: hidden;
}

.ranking-card, .chart-card, .map-card {
  flex: 1;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(0, 255, 255, 0.2);
  border-radius: 12px;
  padding: 20px;
  backdrop-filter: blur(20px);
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
}

.map-card {
  padding: 5px 20px 20px 20px;
  overflow: hidden;
  height: 100%;
  position: relative;
  box-shadow: 
    0 8px 32px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
  transition: all 0.3s ease;
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 
      0 12px 40px rgba(0, 0, 0, 0.5),
      inset 0 1px 0 rgba(255, 255, 255, 0.15);
  }
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(0, 255, 255, 0.2);
  flex-shrink: 0;

  h3 {
    font-size: 18px;
        font-weight: 600;
    margin: 0;
    color: #fff;
    text-shadow: 0 0 4px rgba(0, 255, 255, 0.2);
    position: relative;
    
    &::after {
      content: '';
      position: absolute;
      bottom: -12px;
      left: 0;
      width: 30px;
      height: 2px;
      background: linear-gradient(90deg, rgba(0, 255, 255, 0.8), transparent);
      border-radius: 1px;
    }
  }

  // 省份状态指示器
  .province-status {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    background: rgba(0, 255, 255, 0.1);
    border: 1px solid rgba(0, 255, 255, 0.3);
    border-radius: 8px;
    backdrop-filter: blur(10px);

    .status-label {
      font-size: 12px;
      color: rgba(255, 255, 255, 0.7);
    }

    .province-name {
      font-size: 14px;
      font-weight: 600;
      color: #4fc3f7;
      text-shadow: 0 0 4px rgba(79, 195, 247, 0.5);
    }

    .reset-btn {
      background: linear-gradient(45deg, #4fc3f7, #29b6f6);
      border: none;
      border-radius: 6px;
      padding: 4px 8px;
      font-size: 11px;
      font-weight: 500;
      color: #fff;
      cursor: pointer;
      transition: all 0.3s ease;

      &:hover {
        background: linear-gradient(45deg, #29b6f6, #0288d1);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(79, 195, 247, 0.3);
      }
    }
  }

  // 连接状态指示器
  .connection-status {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 6px;
    backdrop-filter: blur(5px);

    .status-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      animation: statusPulse 2s ease-in-out infinite;

      &.connected {
        background: #4caf50;
        box-shadow: 0 0 8px rgba(76, 175, 80, 0.6);
      }

      &.disconnected {
        background: #f44336;
        box-shadow: 0 0 8px rgba(244, 67, 54, 0.6);
      }
    }

    .status-text {
      font-size: 11px;
      color: rgba(255, 255, 255, 0.8);
      font-weight: 500;
    }
  }
}

.card-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}

.empty-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
}

.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: rgba(0, 255, 255, 0.8);
  font-size: 14px;
  
  .loading-spinner-small {
    width: 24px;
    height: 24px;
    border: 2px solid rgba(0, 255, 255, 0.3);
    border-top: 2px solid rgba(0, 255, 255, 0.8);
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: 12px;
  }
}

.no-data-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
}

.chart-container {
  width: 100%;
  height: 100%;
  min-height: 300px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

      .ranking-list {
    flex: 1;
        overflow-y: auto;
    
    /* 隐藏滚动条但保持滚动功能 */
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* IE and Edge */
    
    /* 平滑滚动 */
    scroll-behavior: smooth;
    
    &::-webkit-scrollbar {
      display: none; /* Chrome, Safari, Opera */
    }
    
    /* 鼠标悬停时的样式 */
    &:hover {
      cursor: pointer;
    }
  }

        .ranking-item {
          display: flex;
          align-items: center;
          padding: 15px 0;
          border-bottom: 1px solid rgba(0, 255, 255, 0.1);
          transition: all 0.3s ease;
          position: relative;

          &:hover {
            background: rgba(0, 255, 255, 0.05);
            border-radius: 8px;
            margin: 0 -12px;
            padding: 15px 12px;
            box-shadow: 0 4px 15px rgba(0, 255, 255, 0.1);
            
            &::before {
              content: '';
              position: absolute;
              left: 0;
              top: 0;
              bottom: 0;
              width: 3px;
              background: linear-gradient(180deg, rgba(0, 255, 255, 0.8), rgba(255, 0, 255, 0.6));
              border-radius: 0 2px 2px 0;
            }
          }

          &:last-child {
            border-bottom: none;
          }

          .rank-number {
            width: 28px;
            height: 28px;
            background: linear-gradient(45deg, rgba(0, 255, 255, 0.8), rgba(255, 0, 255, 0.6));
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: bold;
            margin-right: 12px;
            flex-shrink: 0;
          }

          .item-info {
            flex: 1;
            min-width: 0;

            .item-name {
              font-size: 14px;
              font-weight: 500;
              margin-bottom: 4px;
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
            }

            .item-details {
              display: flex;
              gap: 8px;
              font-size: 12px;
      color: rgba(255, 255, 255, 0.7);

              .price {
        color: #4fc3f7;
                font-weight: 500;
              }

              .hospital {
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                max-width: 120px;
            }
          }

          .view-count {
            font-size: 12px;
      color: #66bb6a;
      margin-top: 4px;
    }
  }
}

.map-container {
  flex: 1;
  position: relative;
  min-height: 500px;
  height: 100%;
  padding: 5px 0 10px 0;
  overflow: visible;
  z-index: 1;
}

.map-stats-overlay {
  position: absolute;
  top: 10px;
  left: 20px;
  right: 20px;
          display: flex;
  justify-content: space-around;
  padding: 12px 20px;
  background: rgba(0, 0, 0, 0.7);
  border-radius: 12px;
  border: 1px solid rgba(0, 255, 255, 0.3);
  z-index: 2;
  pointer-events: none;
  flex-shrink: 0;
  backdrop-filter: blur(15px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
}

.stat-item {
  text-align: center;
            flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border-radius: 8px;
  transition: all 0.3s ease;

  &:hover {
    background: rgba(0, 255, 255, 0.1);
  }
}

.stat-value {
  font-size: 20px;
  font-weight: bold;
  color: #fff;
  text-shadow: 0 0 8px rgba(0, 255, 255, 0.5);
}

.stat-label {
            font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
            font-weight: 500;
  letter-spacing: 0.5px;
}


// 确保在任何情况下都没有白边
.dashboard-wrapper::after {
  content: '';
  position: fixed;
  top: -10px;
  left: -10px;
  right: -10px;
  bottom: -10px;
  background: linear-gradient(135deg, #0a0e27 0%, #1a1f3a 50%, #0f1419 100%);
  z-index: -2;
}

// 移除响应式设计，使用固定布局通过transform缩放

/* 移除所有媒体查询，让JavaScript完全控制缩放 */
</style>